<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2022/7/23 0023
 * Time: 17:20
 */

namespace framework\library;

use framework\library\Response;

class Dispatch
{
    protected $app;

    // 路由调度：注入请求对象和路由对象
    public function run($app, $request, $route)
    {
        $this->app = $app;
        $data = null;
        $method = $request->getHttpMethod();
        $uri = $request->getUri();
        $staticRoute = $route->getStaticRoute();
        $dynamicRoute = $route->getDynamicRoute();
        $uniRoute = [$staticRoute, $dynamicRoute];

        foreach ($uniRoute as $key => $value) {
            if (array_key_exists($method, $value)) {
                $uriArr = $value[$method];
                if (array_key_exists($uri, $uriArr)) {
                    $handler = $uriArr[$uri];
                    // 判断是否闭包
                    if ($handler instanceof \Closure) {
                        $data = $handler();
                    } else {
                        $data = $this->action($handler);
                    }
                }
            }
        }
        return $this->autoResponse($data);
    }

    protected function autoResponse($data)
    {
        if ($data instanceof Response) {
            $response = $data;
        } elseif (!is_null($data)) {
            // 创建response对象, 可以根据app.config中读取返回项
            $type = "json";
            $response = Response::create($data, $type);
        } else {
            $data = ob_get_contents();
            $response = Response::create($data, '');
        }

        return $response;
    }

    // 实例化对应的控制器和方法
    protected function action($handler)
    {
        $data = null;
        list($module, $controller, $action) = explode("/", $handler);
        $classname = "\\app\\".$module."\controller\\".$controller."Controller";
        if (class_exists($classname)) {
            $obj = new $classname;
            $data = $obj->$action();
        } else {
            throw new Exception(422, "{$classname}类不存在！");
        }

        return $data;
    }


}